package com.gsi.webstore.platform.storefront.pipelet.orderprocess;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import com.gsi.webstore.platform.adapter.storelocator.capi.StoreLocatorManager;
import com.gsi.webstore.platform.adapter.storelocator.internal.client.data.Storefront;
import com.intershop.beehive.bts.capi.orderprocess.ProductLineItem;
import com.intershop.beehive.bts.capi.orderprocess.basket.Basket;
import com.intershop.beehive.core.capi.naming.NamingMgr;
import com.intershop.beehive.core.capi.pipeline.Pipelet;
import com.intershop.beehive.core.capi.pipeline.PipeletExecutionException;
import com.intershop.beehive.core.capi.pipeline.PipelineDictionary;
import com.intershop.beehive.core.capi.pipeline.PipelineInitializationException;
import com.intershop.beehive.xcs.capi.product.Product;
import com.intershop.beehive.xcs.capi.product.ProductMgr;
import com.intershop.beehive.xcs.common.ProductRef;
import com.intershop.component.shipping_data.capi.shippingmethod.ShippingMethod;

/**
 * This pipelet validates the product eligibility,to check if product is
 * eligible for what it was eligible before and if product is eligible then
 * check for store eligibility, to check if store is eligible for what it was
 * eligible before.
 */
public class ValidateStoreEligibilityForLineItems extends Pipelet
{

    /**
     * Constant used to access the pipeline dictionary with key 'Cart'
     * 
     * Basket
     */
    public static final String DN_CART = "Cart";
    /**
     * Constant used to access the pipeline dictionary with key 'LocaleID'
     * 
     * Locale ID
     */
    public static final String DN_LOCALE_ID = "LocaleID";
    /**
     * Constant used to access the pipeline dictionary with key 'ResultMap'
     * 
     * The map of the line item uuids and the corresponding eligibility fail
     * messages
     */
    public static final String DN_RESULT_MAP = "ResultMap";
    /**
     * Constant used to access the pipeline dictionary with key
     * 'ResultMapKeyIterator'
     * 
     * Iterator of the keys of ResultMap
     */
    /**
     * Constant used to access the product manager
     */
    private ProductMgr productMgr = null;
    /**
     * Constant used to access the store locator manager
     */
    private StoreLocatorManager storeLocationMgr = null;
       
    public static final String DN_RESULT_MAP_KEY_ITERATOR = "ResultMapKeyIterator";
    public static final String FULFILMENT_METHOD_ISPU = "ISPU";
    public static final String FULFILMENT_METHOD_STS = "STS";
    public static final String storeFrontIdAttribute = "STORE_ID";
    public static final String storeCodeAttribute = "STORE_CODE";
    public static final String multichannelFulfillmentMethodAttribute = "MC_FULFILLMENT_METHOD";
    public static final String STORE_NOT_STS = "STORE_NOT_STS";
    public static final String STORE_NOT_ISPU = "STORE_NOT_ISPU";
    public static final String PROD_NOT_ISPU_OR_STS = "PROD_NOT_ISPU_OR_STS";
    //public static final String PROD_NOT_STS = "PROD_NOT_STS";
    //public static final String PROD_NOT_ISPU = "PROD_NOT_ISPU";
    public static final String STORE_NOT_STS_PROD_NOT_ISPU = "STORE_NOT_STS_PROD_NOT_ISPU";
    public static final String PROD_NOT_STS_BUT_ISPU = "PROD_NOT_STS_BUT_ISPU";
    public static final String PROD_NOT_ISPU_BUT_STS = "PROD_NOT_ISPU_BUT_STS";
    public static final String NO_STORE_ASSOCIATED = "NO_STORE_ASSOCIATED";
    /**
     * Constant used to access the pipeline dictionary with key 'StorefrontCartLineItemsMap'
     */
    public static final String DN_STOREFRONT_CART_LINE_ITEMS_MAP = "StorefrontCartLineItemsMap";
    /**
     * Constant used to access the pipeline dictionary with key 'PreferenceMap'
     */
    public static final String DN_PREFERENCE_MAP = "PreferenceMap";
    /**
     * Constant used to access the pipeline dictionary with key 'DefaultShippingMethod'
     */
    public static final String DN_DEFAULT_SHIPPING_METHOD = "DefaultShippingMethod";

    /**
     * The pipelet's execute method is called whenever the pipelets gets
     * executed in the context of a pipeline and a request. The pipeline
     * dictionary valid for the currently executing thread is provided as a
     * parameter.
     * 
     * @param dict
     *            The pipeline dictionary to be used.
     * @throws PipeletExecutionException
     *             Thrown in case of severe errors that make the pipelet execute
     *             impossible (e.g. missing required input data).
     */
    public int execute(PipelineDictionary dict) throws PipeletExecutionException
    {        
        // lookup 'DefaultShippingMethod' in pipeline dictionary
        ShippingMethod defaultShippingMethod = (ShippingMethod)dict.get(DN_DEFAULT_SHIPPING_METHOD);
        
        // lookup 'PreferenceMap' in pipeline dictionary
        Map preferenceMap = (Map)dict.get(DN_PREFERENCE_MAP);

        // lookup 'LocaleID' in pipeline dictionary
        String localeID = (String)dict.get(DN_LOCALE_ID);
        if (null == localeID)
        {
            throw new PipeletExecutionException(
                            "Mandatory input parameter 'LocaleID' not available in pipeline dictionary.");
        }

        // lookup 'Cart' in pipeline dictionary
        Basket cart = (Basket)dict.get(DN_CART);
        if (null == cart)
        {
            throw new PipeletExecutionException(
                            "Mandatory input parameter 'Cart' not available in pipeline dictionary.");
        }
        // initialize variables
        String result = null;
        ProductRef productRef;
        Product product;
        String multichannelShipToStoreEnabled = "Multichannel / Ship To Store Enabled";
        String multichannelInStorePickupEnabled = "Multichannel / In Store Pickup Enabled";
        //String pliShippingMethod = "";
        
        HashMap<String, String> resultMap = new HashMap<String, String>();
        Iterator<String> resultMapKeyIterator = null;
        
        // create an iterator for cart product line items
        Iterator<ProductLineItem> lineItemIterator = cart.createProductLineItemsOrderedByPositionIterator();
        Storefront storefront = null;
        if (lineItemIterator != null)
        {
            while(lineItemIterator.hasNext())
            {
                String pliMultichannelFulfillmentMethod= "";
                long pliStoreID = 0;
                boolean productSTSEligibility = false;
                boolean productISPUEligibility = false;
                boolean storeSTSEligibility = false;
                boolean storeISPUEligibility = false;
                
                ProductLineItem productLineItem = (ProductLineItem)lineItemIterator.next();
                productRef = productLineItem.getOfferProductRef();

                // get product from product line item
                product = productMgr.getProductByProductRef(productRef);

                // TODO: remove this quick hack created for #VPRS-2020 and exclude ad-hoc PLIs from entering any shipping calculation methods
                if (product != null) {
                    // Begin of getting value of multichannel attributes for product
                    if (product.containsAttribute(multichannelShipToStoreEnabled))
                    {
                        productSTSEligibility = (Boolean)product.getAttribute(multichannelShipToStoreEnabled);
                    }
                    if (product.containsAttribute(multichannelInStorePickupEnabled))
                    {
                        productISPUEligibility =(Boolean)product.getAttribute(multichannelInStorePickupEnabled);
                    }
                    // end of getting value of multichannel attributes
                }

                // Get shipping method from line item
                //if (productLineItem.getShippingMethod() != null)
               // {
                //    pliShippingMethod = productLineItem.getShippingMethod().getId();
               // }
                if (productLineItem.containsAttribute(multichannelFulfillmentMethodAttribute))
                {
                    pliMultichannelFulfillmentMethod=(String)productLineItem.getAttribute(multichannelFulfillmentMethodAttribute);
                }

                // check for webstore eligibility
                if(preferenceMap.get("ISPUEnabledValue").equals("true") || preferenceMap.get("STSEnabledValue").equals("true"))
                {
                 // Check for product eligibility
                    if (productSTSEligibility || productISPUEligibility)
                    {
                        if (productLineItem.containsAttribute(storeFrontIdAttribute))
                        {
                            pliStoreID = (Long)productLineItem.getAttribute(storeFrontIdAttribute);
                        }
                        
                        
                        // get store
                        if (pliStoreID != 0 )
                        {
                            storefront = storeLocationMgr.getStorefront(pliStoreID, localeID);
                            // get store eligibility attributes
                            if (storefront != null)
                            {
                                storeISPUEligibility = storefront.isInStorePickUpEligible();
                                storeSTSEligibility = storefront.isSTSEligible();
                            }
                        }
                        // end of get store
                        if ((FULFILMENT_METHOD_STS).equalsIgnoreCase(pliMultichannelFulfillmentMethod) && preferenceMap!=null)
                        {
                            if((!productSTSEligibility || preferenceMap.get("STSEnabledValue").equals("false"))&& productISPUEligibility && preferenceMap.get("ISPUEnabledValue").equals("true"))
                            {
                                result= PROD_NOT_STS_BUT_ISPU;
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute); 
                                productLineItem.removeAttribute(multichannelFulfillmentMethodAttribute);
                                // set default shipping method
                                if(defaultShippingMethod != null)
                                {
                                    productLineItem.setShippingMethod(defaultShippingMethod);
                                }
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                                                        
                            else if (!storeSTSEligibility && productSTSEligibility && productISPUEligibility && preferenceMap.get("ISPUEnabledValue").equals("true"))//and kill switch ISPU on condition
                            {
                                result = STORE_NOT_STS; // product eligible but store not eligible for STS
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);                        
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                            
                            else if(!storeSTSEligibility && productSTSEligibility && (!productISPUEligibility || preferenceMap.get("ISPUEnabledValue").equals("false")))// or kill switch ISPU off condition
                            {
                                result=STORE_NOT_STS_PROD_NOT_ISPU;
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);  
                                resultMap.put(productLineItem.getUUID(), result);
                                
                            }
                            
                           else if (storeSTSEligibility && productSTSEligibility && preferenceMap.get("STSEnabledValue").equals("false"))
                            {
                                result = STORE_NOT_STS; // product eligible,store eligible for STS but STS preference off.
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);                        
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                           
                            else if (storefront==null && (productSTSEligibility || productISPUEligibility))
                            {
                                result = NO_STORE_ASSOCIATED; // product eligible but store not eligible for STS or store information already removed.
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);                        
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                        }
                        else if ((FULFILMENT_METHOD_ISPU).equalsIgnoreCase(pliMultichannelFulfillmentMethod)&& preferenceMap!=null)
                        {
                            if((!productISPUEligibility || preferenceMap.get("ISPUEnabledValue").equals("false"))&& productSTSEligibility && preferenceMap.get("STSEnabledValue").equals("true"))
                            {
                                result= PROD_NOT_ISPU_BUT_STS;
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute); 
                                productLineItem.removeAttribute(multichannelFulfillmentMethodAttribute);
                                // set default shipping method
                                if(defaultShippingMethod != null)
                                {
                                    productLineItem.setShippingMethod(defaultShippingMethod);
                                }
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                             
                            else if (!storeISPUEligibility && productISPUEligibility && productSTSEligibility &&  preferenceMap.get("STSEnabledValue").equals("true"))//and kill switch STS on  
                            {
                                result = STORE_NOT_ISPU; // product eligible but store not eligible for ISPU
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);  
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                            
                            else if(!storeISPUEligibility && productISPUEligibility && (!productSTSEligibility ||preferenceMap.get("STSEnabledValue").equals("false")))// or kill switch STS off 
                            {
                                result=STORE_NOT_STS_PROD_NOT_ISPU;
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);  
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                           
                            else if (storeISPUEligibility && productISPUEligibility && productSTSEligibility && preferenceMap.get("ISPUEnabledValue").equals("false") && preferenceMap.get("STSEnabledValue").equals("true"))
                            {
                                result = STORE_NOT_ISPU; // product eligible,store eligible for ISPU but ISPU preference off.
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);                        
                                resultMap.put(productLineItem.getUUID(), result);
                            }
                            
                            else if (storefront==null && (productSTSEligibility || productISPUEligibility))
                            {
                                result = NO_STORE_ASSOCIATED; // product eligible but store not eligible for ISPU or store information already removed.
                                productLineItem.removeAttribute(storeCodeAttribute);                     
                                productLineItem.removeAttribute(storeFrontIdAttribute);                        
                                resultMap.put(productLineItem.getUUID(), result);
                            }


                        }
                      
                    }
                    else
                    {
                        // product no longer eligible for ISPU/STS
                        // remove store info and set to shipping
                        if (pliMultichannelFulfillmentMethod.equals(FULFILMENT_METHOD_STS) || pliMultichannelFulfillmentMethod.equals(FULFILMENT_METHOD_ISPU))
                        {
                            productLineItem.removeAttribute(storeCodeAttribute);
                            productLineItem.removeAttribute(storeFrontIdAttribute);
                            productLineItem.removeAttribute(multichannelFulfillmentMethodAttribute);
                            // set default shipping method
                            if(defaultShippingMethod != null)
                            {
                                productLineItem.setShippingMethod(defaultShippingMethod);
                            }
                            result = PROD_NOT_ISPU_OR_STS; // product not eligible for STS/ISPU
                            resultMap.put(productLineItem.getUUID(), result);
                        }
                    } 
                }
                // web store preferences kill switches are off
                else
                {

                    // remove store info and set to shipping
                    if (pliMultichannelFulfillmentMethod.equals(FULFILMENT_METHOD_STS) || pliMultichannelFulfillmentMethod.equals(FULFILMENT_METHOD_ISPU))
                    {
                        productLineItem.removeAttribute(storeCodeAttribute);
                        productLineItem.removeAttribute(storeFrontIdAttribute);
                        productLineItem.removeAttribute(multichannelFulfillmentMethodAttribute);
                        // set default shipping method
                        if(defaultShippingMethod != null)
                        {
                            productLineItem.setShippingMethod(defaultShippingMethod);
                        }
                        result = PROD_NOT_ISPU_OR_STS; // product not eligible for STS/ISPU
                        resultMap.put(productLineItem.getUUID(), result);
                    }
                }
                

            }
            if (resultMap != null)
            {
                resultMapKeyIterator = resultMap.keySet().iterator();
            }

        }

        // store 'ResultMap' in pipeline dictionary
        // TODO Put the value in dictionary
        dict.put(DN_RESULT_MAP, resultMap);

        // store 'ResultMapKeyIterator' in pipeline dictionary
        // TODO Put the value in dictionary
        dict.put(DN_RESULT_MAP_KEY_ITERATOR, resultMapKeyIterator);
        
        return PIPELET_NEXT;
    }

      public void init() throws PipelineInitializationException
    {
        productMgr = (ProductMgr)NamingMgr.getInstance().lookupManager("ProductMgr");
        storeLocationMgr = (StoreLocatorManager)NamingMgr.getManager(StoreLocatorManager.class);
        
        
    }
}